golang环境下安装 swagger

安装 swagger

1
$ go get -u -v github.com/swaggo/swag/cmd/swag

若 $GOPATH/bin 没有加入$PATH中,你需要执行将其可执行文件移动到$GOBIN下

1
$ mv $GOPATH/bin/swag /usr/local/go/bin

验证是否安装成功

1
2
$ swag -v
swag version v1.1.1

安装 gin-swagger

1
2
3
$ go get -u -v github.com/swaggo/gin-swagger

$ go get -u -v github.com/swaggo/gin-swagger/swaggerFiles

注:三个包都有一定大小,安装需要等一会

初始化

编写API注释

Swagger 中需要将相应的注释或注解编写到方法上,再利用生成器自动生成说明文件

gin-swagger 给出的范例:

1
2
3
4
5
6
7
8
9
// @Summary Add a new pet to the store
// @Description get string by ID
// @Accept json
// @Produce json
// @Param some_id path int true "Some ID"
// @Success 200 {string} string "ok"
// @Failure 400 {object} web.APIError "We need ID!!"
// @Failure 404 {object} web.APIError "Can not find ID"
// @Router /testapi/get-string-by-int/{some_id} [get]

参照 Swagger 的注解规范和范例去编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// @title Swagger for yhbaas
// @version 1.0
// @description 提供一站式配置、开发、测试、部署和运维的区块链服务平台.

// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html

// @host localhost:9999/
// @BasePath

func main() {
router = gin.Default()
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
router.Run(":9999")
}

在对应的方法体中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// GetPeersCanInit
// @Summary 查询可以初始化的节点
// @Description GetPeersCanInit
// @Accept json
// @Tags GetPeersCanInit
// @Security Bearer
// @Produce json
// @Param chaincodeID path string true "chaincodeID"
// @Param channelId path string true "channelId"
// @Resource ID
// @Success 200 {object} structs.BCNodeInfo
// @Failure 500 {object} httputil.HTTPError
// @Router /network/peersCanInit/{channelId}/{chaincodeID} [get]
func GetPeersCanInit(c *gin.Context) {
chaincodeID := c.Params.ByName("chaincodeID")
channelIdStr := c.Params.ByName("channelId")
//...
c.JSON(http.StatusOK, gin.H{
"bcNodeInfo": bcNodeInfo,
})
}

参考的注解可见 gin-blog

生成

我们进入到yhbaas的项目根目录中(main.go所在同级目录下/yhbaas/backend),执行初始化命令

1
2
3
4
/yhbaas/backend$ swag init
2018/10/15 10:40:10 Generate swagger docs....
2018/10/15 10:40:10 Generate general API Info
2018/10/15 10:40:10 create docs.go at docs/docs.go

完毕后会在项目根目录(main.go所在同级目录下/yhbaas/backend)下生成docs

1
2
3
4
5
docs/
├── docs.go
└── swagger
├── swagger.json
└── swagger.yaml

我们可以检查 docs.go 文件中的 doc 变量,详细记载中我们文件中所编写的注解和说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
// This file was generated by swaggo/swag at
// 2018-10-12 16:36:46.110316843 +0800 CST m=+13.550947436

package docs

import (
"bytes"

"github.com/alecthomas/template"
"github.com/swaggo/swag"
)

var doc = `{
"swagger": "2.0",
"info": {
"description": "提供一站式配置、开发、测试、部署和运维的区块链服务平台.",
"title": "Swagger for yhbaas",
"termsOfService": "http://swagger.io/terms/",
"contact": {},
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"version": "1.0"
},
"host": "petstore.swagger.io",
"basePath": "/v1",
"paths": {
"/allChannels/{netId}": {
"get": {
"security": [
{
"Bearer": []
}
],
"description": "GetAllChannels by netId",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"GetOrg"
],
"summary": "GetAllChannels",
"parameters": [
{
"type": "string",
"description": "netId",
"name": "netId",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "object",
"$ref": "#/definitions/structs.ChannelInfo"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"type": "object",
"$ref": "#/definitions/httputil.HTTPError"
}
}
}
}
},

验证

大功告成,访问一下 http://127.0.0.1:9999/swagger/index.html, 查看 API 文档生成是否正确

补充:

API 操作

注解 描述
description 描述,操作行为的详细解释
id ID,用于识别操作的唯一字符串。在所有API操作中必须是唯一的
tags 标签,A list of tags to each API operation that separated by commas
summary 概要,A short summary of what the operation does
accept API可以使用的MIME类型列表。值必须如MIME类型所述
produce API可以生成的MIME类型列表。值必须如MIME类型所述
param 参数, 以空格分隔的参数 param name,param type,data type,is mandatory?,comment attribute(optional)
security 安全性
success 以空格分隔的成功响应。 return code,{param type},data type,comment
failure 以空格分隔的失败响应。 return code,{param type},data type,comment
router 访问路径。 path,[httpMethod]

Mime 类型

1
2
3
4
5
6
7
8
9
10
11
12
json
application/json
xml
text/xml
plain
text/plain
html
text/html
mpfd
multipart/form-data
json-api
application/vnd.api+json

安全

一般API信息

1
2
3
4
5
// @securityDefinitions.basic BasicAuth
// @securitydefinitions.oauth2.application OAuth2Application
// @tokenUrl https://example.com/oauth/token
// @scope.write Grants write access
// @scope.admin Grants read and write access to administrative information

每个API操作

1
// @Security ApiKeyAuth

创建和条件

1
2
// @Security ApiKeyAuth
// @Security OAuth2Application[write, admin]

参数类型

1
2
3
4
5
6
object (struct)
string (string)
integer (int, uint, uint32, uint64)
number (float32)
boolean (bool)
array

数据类型

1
2
3
4
5
string (string)
integer (int, uint, uint32, uint64)
number (float32)
boolean (bool)
user defined struct

属性

1
2
3
4
5
6
// @Param enumstring 查询字符串false“字符串枚举”枚举(A,B,C)
// @Param enumint 查询int int“int enums”枚举(1,2,3)
// @Param 枚举查询编号false“int枚举“枚举(1.1,1.2,1.3)
// @Param 字符串查询字符串假”字符串有效“minlength(5)maxlength(10)
// @Param int查询int假”int valid“mininum(1)maxinum(10)
// @Param 默认查询字符串false“字符串默认”默认(A)

具有数组类型的用户定义结构

1
// @Success 200 {array} model.Account
1
2
3
4
5
6
<-- This is a user defined struct.
package model
type Account struct {
ID int `json:"id" example:"1"`
Name string `json:"name" example:"account name"`
}

使用多个路径参数

1
2
3
4
5
/// ...
// @Param group_id path int true "Group ID"
// @Param account_id path int true "Account ID"
// ...
// @Router /examples/groups/{group_id}/accounts/{account_id} [get]

结构体的例子

1
2
3
4
5
6
7
// 节点信息表
type BCNodeInfo struct {
NodeID int32 `gorm:"AUTO_INCREMENT;primary_key"`
NodeName string `json:"nodeName"` //peer0.org1
OrgID int32 `json:"orgID"`
RunStatus RunStatusType `json:"runStatus"`
}